/* LunaPort is a Vanguard Princess netplay application
 * Copyright (C) 2009 by Anonymous
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef CODE_H
#define CODE_H

#include <map>
#include <list>
#include "LunaPort.h"

// code to inject, breakpoints, magic numbers
#define RANDOM_SEED 0x0041fb1c

#define STAGE_SELECT 0x00408756
unsigned char stage_select[] = {0xE9, 0x95, 0x2E, 0x01, 0x00};

#define STAGE_SELECT_FUNC 0x0041B5F0
#define STAGE_SELECT_BREAK 0x0041B5F6
unsigned char stage_select_func[] = {0x90,0xE8,0x2C,0xC4,0xFF,0xFF,0xCC,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0xE9,0x52,0xD1,0xFE,0xFF};

#define CONTROL_CHANGE 0x0041B588
#define P1_KBD_CONTROLS 0x00425980
#define P2_KBD_CONTROLS 0x00425991
#define KBD_CONTROLS_LEN 10
unsigned char kbd_control_buffer[KBD_CONTROLS_LEN];

#define P1_JOY_CONTROLS 0x00445710
#define P2_JOY_CONTROLS 0x00445717
#define JOY_CONTROLS_LEN 7
unsigned char joy_control_buffer[JOY_CONTROLS_LEN];

#define KBD_WRITEBACK 0x00414FCA
unsigned char kbd_writeback[] = {0x90,0x8B,0x15,0x7C,0x1F,0x54,0x00,0x90,0x90,0x90,0x90,0x90};

#define JOY_WRITEBACK 0x0041502C
unsigned char joy_writeback[] = {0x90,0x8B,0x15,0x7C,0x1F,0x54,0x00,0x90,0x90,0x90,0x90,0x90};

#define STICK_SELECTION 0x004144CB
unsigned char stick_selection[] = {0x6A,0x00};

#define LOCAL_P_FUNC 0x0041B588
#define LOCAL_P_BREAK 0x0041B591
unsigned char local_p_func[] = {0xCC,0x90,0x90,0x90,0xE8,0xAF,0x8D,0xFF,0xFF,0xCC,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90};

#define LOCAL_P_JMPBACK 0x0041B5B9
unsigned char local_p_jmpback[2][5] = {{0xE9,0x82,0x91,0xFF,0xFF},{0xE9,0x9D,0x91,0xFF,0xFF}}; // 0 = local is p1, 1 = local is p2

#define REMOTE_P_FUNC 0x0041B5BE
#define REMOTE_P_BREAK 0x0041B5C0
unsigned char remote_p_func[] = {0x90,0x90,0xCC,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90};

#define REMOTE_P_JMPBACK 0x0041B5E3
unsigned char remote_p_jmpback[2][5] = {{0xE9,0x58,0x91,0xFF,0xFF},{0xE9,0x73,0x91,0xFF,0xFF}}; // 0 = remote is p1, 1 = remote is p2

#define P1_JUMP 0x0041473b
unsigned char p1_jump[2][5] = {{0xE9,0x48,0x6E,0x00,0x00},{0xE9,0x7E,0x6E,0x00,0x00}}; // 0 = local is p1, 1 = remote is p1 (corresponds to jump back local)

#define P2_JUMP 0x00414756
unsigned char p2_jump[2][5] = {{0xE9,0x2D,0x6E,0x00,0x00},{0xE9,0x63,0x6E,0x00,0x00}}; // 0 = local is p2, 1 = remote is p2 (corresponds to jump back remote)

// we have some separate hooks for local replay recording

#define REPLAY_HOOKS 0x0041B760
unsigned char replay_hooks[] = {0xE8,0xDB,0x8B,0xFF,0xFF,0xCC,0xE9,0xD5,0x8F,0xFF,0xFF,0xE8,0xD0,0x8B,0xFF,0xFF,0xCC,0xE9,0xE5,0x8F,0xFF,0xFF};

#define REPLAY_P1_JUMP 0x0041473B
#define REPLAY_P1_BREAK 0x0041B765
unsigned char replay_p1_jump[] = {0xE9,0x20,0x70,0x00,0x00};

#define REPLAY_P2_JUMP 0x00414756
#define REPLAY_P2_BREAK 0x0041B770
unsigned char replay_p2_jump[] = {0xE9,0x10,0x70,0x00,0x00};

// controls for single player mode are separate

#define SINGLE_FUNC 0x0041B776
#define SINGLE_BREAK_CONTROL 0x0041B776
#define SINGLE_BREAK_INPUT 0x0041B77C
unsigned char single_func[] = {0xCC,0xE8,0xC4,0x8B,0xFF,0xFF,0xCC,0xE9,0x9E,0x8F,0xFF,0xFF};

#define SINGLE_JUMP 0x0041471B
unsigned char single_jump[] = {0xE9,0x56,0x70,0x00,0x00};


// hook for frame rate grabber
#define FRAME_FUNC 0x0041B782
#define FRAME_BREAK 0x0041B782
unsigned char frame_func[] = {0xCC,0xA1,0x6C,0x47,0x42,0x00,0xE9,0x88,0x94,0xFE,0xFF};

#define FRAME_JUMP 0x00404C10
unsigned char frame_jump[] = {0xE9,0x6D,0x6B,0x01,0x00};

#define TITLE_BREAK 0x00403F4E
unsigned char title_break[] = {0xCC};
unsigned char title_break_bak[] = {0x52};


// replay playback speed input counter
#define GAME_SPEED 0x0041E2F0
#define KEYSTATES 0x00424D20
#define WAITSKIP 100
#define SPEED_MOD 3

#define EXTRA_INPUT_JUMP 0x00405B45
unsigned char extra_input_jump[] = {0xE9,0x56,0x5C,0x01,0x00,0x90};

#define IMPORT_KBD_CALL 0x004146D9 // read from here
#define EXPORT_KBD_CALL 0x0041B7B1 // write here
unsigned char import_kbd_call[6];

#define EXTRA_INPUT_FUNC 0x0041B7A0
#define EXTRA_INPUT_WAIT_BREAK 0x0041B7A6
#define EXTRA_INPUT_BREAK 0x0041B7B7
#define EXTRA_INPUT_GO 0x0041B7AC
#define EXTRA_INPUT_BACK 0x00405B4A
unsigned char extra_input_func[] = {0x8B,0x35,0xF0,0xE2,0x41,0x00,0xCC,0xE9,0x9E,0xA3,0xFE,0xFF,0x68,0x20,0x4D,0x42,0x00,0x90,0x90,0x90,0x90,0x90,0x90,0xCC};


// information
#define P1_CHAR_NUM 0x00470020
#define P2_CHAR_NUM 0x00470024
#define STAGE_NUM   0x00470040
#define CHAR_NAMES  0x00435474 // array, 256B per name
#define STAGE_NAMES 0x0043A29C // array, 256B per name


// simple INT3/single-step breakpoints
#define LOAD_STAGE_BREAK 0x004041E0
#define DOUBLE_KO_BREAK 0x00408FCF
#define DRAW_BREAK 0x00408FF7
#define P1_WIN_BREAK 0x0040901F
#define P2_WIN_BREAK 0x00409043
unsigned int simple_int3[] = {LOAD_STAGE_BREAK, DOUBLE_KO_BREAK, DRAW_BREAK, P1_WIN_BREAK, P2_WIN_BREAK, 0};
std::map<const DWORD, char> simple_int3_backups;
std::list<DWORD> simple_int3_reset;


// fps hack
#define FPS_HACK 0x00405B45
#define MAX_INPUTS_PER_FRAME 0x00405BC7
unsigned char fps_hack_func[] = {0x8B,0x35,0xF0,0xE2,0x41,0x00,0xFF,0x15,0x2C,0xC2,0x41,0x00,0x8B,0x0D,0xD4,0x7D,0x44,0x00,0x3B,0xC8,0x73,0xF0,0x03,0xCE,0x90,0x89,0x0D,0xD4,0x7D,0x44,0x00,0x8B,0x0D,0xE0,0x7E,0x44,0x00,0xB8,0x0D,0xFD,0x4D,0x00,0x89,0x68,0xFC,0x89,0x08,0x05,0x3F,0xE0,0x00,0x00,0x3D,0x05,0xFF,0x54,0x00,0x7C,0xEF,0xE8,0x4B,0xEB,0x00,0x00,0xE8,0x46,0xF1,0xFF,0xFF,0x8B,0x0D,0xE0,0x7E,0x44,0x00,0x3E,0x8B,0x14,0x8D,0xE0,0x80,0x42,0x00,0x52,0xE8,0x02,0xCA,0xFF,0xFF,0x83,0xC4,0x04,0xFF,0x15,0x2C,0xC2,0x41,0x00,0x8B,0x0D,0xD4,0x7D,0x44,0x00,0x3B,0xC1,0x73,0x0D,0x89,0x2D,0xF4,0x46,0x42,0x00,0xE8,0x14,0xF2,0xFF,0xFF,0xEB,0x57,0x8B,0x0D,0xF4,0x46,0x42,0x00,0x41,0x83,0xF9,0x09,0x73,0x08,0x89,0x0D,0xF4,0x46,0x42,0x00,0xEB,0x43,0xA3,0xD4,0x7D,0x44,0x00,0xEB,0xD8};

#endif
